// @Author miaoqing
// @Date 2024/11/11 16:57:00
// @Desc
package logic

import (
	"core/common"
	"core/component/logger"
	"sync"
	"time"
)

var (
	world     *World
	worldOnce sync.Once
)

type World struct {
	robots          sync.Map
	msgChan         chan *common.WorldMsgData
	addRobotChan    chan *common.WorldAddRobot
	removeRobotChan chan uint64
	done            chan int
}

func WorldGetMe() *World {
	worldOnce.Do(func() {
		world = &World{
			msgChan:         make(chan *common.WorldMsgData, 64),
			addRobotChan:    make(chan *common.WorldAddRobot, 64),
			removeRobotChan: make(chan uint64, 64),
			done:            make(chan int, 0),
		}
		go world.loop()
	})
	return world
}

func (world *World) loop() {
	for {
		select {
		case msg := <-world.msgChan:
			robot := world.getRobotByID(msg.RobotId)
			if robot != nil {
				robot.msgChan <- msg.RecvData
			}
		case r := <-world.addRobotChan:
			world.addRobot(r.RobotId, r.Address)
		case robotId := <-world.removeRobotChan:
			world.removeRobot(robotId)
		case <-world.done:
			return
		}
	}
}

func (world *World) getRobotByID(robotId uint64) *Robot {
	r, ok := world.robots.Load(robotId)
	if !ok {
		return nil
	}
	return r.(*Robot)
}

func (world *World) addRobot(robotId uint64, address string) {
	if world.getRobotByID(robotId) != nil {
		return
	}
	world.robots.Store(robotId, newRobot(robotId, address))
	logger.Infof("add robot Id %v", robotId)
}

func (world *World) removeRobot(robotId uint64) {
	robot := world.getRobotByID(robotId)
	if robot == nil {
		return
	}
	world.robots.Delete(robotId)
	logger.Infof("remove robot Id %v", robotId)
}

func (world *World) Finialize() {
	world.robots.Range(func(k, v interface{}) bool {
		robot, ok := v.(*Robot)
		if !ok {
			return true
		}
		robot.robotClose()
		return true
	})
	time.Sleep(1 * time.Second)
	world.done <- 1
}
